import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.ArrayList;


public class Turret {

	final double fastToSlow_ratio = 2.0/7; //turn ratio between slow and fast turning rates.
	
	final int activationDistanceSq = (int)(Math.pow(320, 2)); 
	final int activationDistance = 320; //circle with radius 2* hash grid size
	final double minFiringAngleThreshold = 25 * Math.PI/180;
	
	
	final double delayBetweenShots = .7; //seconds
	
	int frameCounter_shots;
	int framesPerShot;
	
	int secondsPerRotate;
	int framerate;

	int rotDir = 1; //Rotation direction: 1 is CW, -1 is CCW.
	double angle;  //Current angle of rotation
	double turnPerFrame_slow; //How much to rotate each frame when idling
	double turnPerFrame_fast; //How much to rotate each frame when tracking
	Point loc; //tiles
	Point turretCenter;
	Point playerLoc;
	boolean isGreen = true;

	
	//Keep track of bullets fired by this gun
	ArrayList<Bullet> bullets;

	
	
	//Warning-circle colors

	public Turret( Point loc, int secondsPerRotate, int framerate){
		this.loc = loc;
		this.turretCenter = new Point( loc.x*40+20, loc.y*40+20);
		
		this.secondsPerRotate = secondsPerRotate;
		this.framerate = framerate;

		this.turnPerFrame_slow = Math.PI*2 / secondsPerRotate / framerate;
		this.turnPerFrame_fast = turnPerFrame_slow/ fastToSlow_ratio;
		this.angle = 0;
		this.isGreen = true;
		this.rotDir = 1;

		this.framesPerShot = (int)Math.round(framerate * delayBetweenShots);
		bullets = new ArrayList<Bullet>();

	}

	public void update(Player player){
		//TODO: calculate the next player position by basic d = vt integration (using a large dT for
		//purposeful inaccuracy, and use that player location instead of player.ctr
		
		
		if( player.ctr.distanceSq(turretCenter.x,turretCenter.y) > activationDistanceSq){
			isGreen = true;
			rotDir = 1;
			angle= (angle + rotDir*turnPerFrame_slow) % (2*Math.PI);
			if(angle < 0)	angle = Math.PI*2 + angle; //make sure angle stays between 0 and 2pi, no negatives
			
			frameCounter_shots = 0;
			
		}else{
			//lock-on-tracking code
			isGreen = false;

			double playerAngle = Math.atan2(player.ctr.x - turretCenter.x, turretCenter.y - player.ctr.y) ;
			playerAngle = (playerAngle<0)? Math.PI*2 + playerAngle : playerAngle; //Turn the [-pi,pi] range to [0, 2pi]
			playerAngle %= Math.PI*2;

			//Find the angle that the turret has to turn: positive means turn CCW, negative means turn CW.
			double deltaAngle = (playerAngle - angle);
			
			//Set which direction to turn
			if(deltaAngle > 0){
				if( deltaAngle > Math.PI){
					rotDir = -1;
				}else
					rotDir = 1;
			}else{
				if( deltaAngle < -Math.PI ){
					rotDir = 1;
				}else
					rotDir = -1;
			}
			
			
			
			//If turret is within 5degrees:
			//Set the turn speed to be slightly slower so we dont spaz back and forth over the target angle
			//Fire shots every time the frameCounter_shots reaches framesPerShot

			if(Math.abs( deltaAngle ) < minFiringAngleThreshold){  
				
				angle= (angle + rotDir*turnPerFrame_slow) % (2*Math.PI);
				if(angle < 0)	angle = Math.PI*2 + angle;
				
				
				//Note: Since the frameCounter starts at 0, and we increment before ever checking for 0,
				//the first time we're tracking it wont immediately shoot - it has to go through a whole
				//loop and reach 0 again.
				frameCounter_shots = (++frameCounter_shots) % framesPerShot;
				
				if(frameCounter_shots == 0){ //let it rip!
					
					//Add a new bullet to the list of bullets we've fired
					double cos = Math.cos(angle);
					double sin = Math.sin(angle);
					
					bullets.add(new Bullet(
							new Point2D.Double( turretCenter.x + sin*20, turretCenter.y + -cos*20 ), 
							new Point2D.Double( sin, -cos), //Unit vector towards where the turret faces
							framerate
					));
				}				
				
			}else{
				angle= (angle + rotDir*turnPerFrame_fast) % (2*Math.PI);
				if(angle < 0)	angle = Math.PI*2 + angle;
			}


		}



	}


	public void reset(){
		angle = 0;
		rotDir = 1;
		playerLoc = null;
		isGreen = true;
		bullets.clear();
		frameCounter_shots = 0;
		
		
	}

	public boolean isGreen(){
		return isGreen;
	}

	public double getAngle(){
		return angle;
	}
	public Point getLocation(){
		return loc;
	}
	public Point getCenterPoint(){
		return turretCenter;
	}



}
